package com.redlight.base;

import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import com.redlight.utils.StringUtil;

import javax.annotation.Resource;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;

//import com.sun.tools.javac.util.Assert;

/**
 * Created by chao on 2019/1/9.
 */
@Transactional
public abstract class BaseService <D extends BaseEntity> {
    protected final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
    @Resource
    private BaseDao<D> baseDao;

    public BaseService() {
    }

    public BaseDao getBaseDao() {
        return this.baseDao;
    }

    public Object save(Object t) {
        Object id = "0";
        String newChildParentIds = null;
        if(t instanceof Map) {
            Map map = (Map)t;
            Object idObj = map.get("id");
            if(null != idObj) {
                id = idObj.toString();
            }
        } else if(t instanceof BaseEntity) {
            BaseEntity bm = (BaseEntity)t;
            id = bm.getId();
        }

        String oldParentIds;
        if(t instanceof SysOrgBase) {
            SysOrgBase ce = (SysOrgBase)t;
            oldParentIds = ce.getParentIds();
            if(!StringUtil.isBlank(ce.getParentId()) && !"0".equals(ce.getParentId())) {
                ce.setParent((SysOrgBase)this.get(ce.getParentId()));
            } else {
                try {
                    ce.setParent((SysOrgBase)ce.getClass().getConstructor(new Class[]{String.class}).newInstance(new Object[]{"0"}));
                } catch (Exception var10) {
//                    Assert.error("no Constructor of class " + ce.getClass().getSimpleName() + " with arguments: String!");
                }
            }

            SysOrgBase pe = ce.getParent();
            if(pe != null) {
                ce.setParentIds(pe.getParentIds() + pe.getId() + ",");
                if(StringUtil.isNotBlank(oldParentIds) && !oldParentIds.equals(ce.getParentIds())) {
                    newChildParentIds = ce.getParentIds() + ce.getId() + ",";
                }
            }
        } else if(t instanceof SysMenuBase) {
            SysMenuBase ce = (SysMenuBase)t;
            oldParentIds = ce.getParentIds();
            if(!StringUtil.isBlank(ce.getParentId()) && !"0".equals(ce.getParentId())) {
                ce.setParent((SysMenuBase)this.get(ce.getParentId()));
            } else {
                try {
                    ce.setParent((SysMenuBase)ce.getClass().getConstructor(new Class[]{String.class}).newInstance(new Object[]{"0"}));
                } catch (Exception var9) {
//                    Assert.error("no Constructor of class " + ce.getClass().getSimpleName() + " with arguments: String!");
                }
            }

            SysMenuBase pe = ce.getParent();
            if(pe != null) {
                ce.setParentIds(pe.getParentIds() + pe.getId() + ",");
                if(StringUtil.isNotBlank(oldParentIds) && !oldParentIds.equals(ce.getParentIds())) {
                    newChildParentIds = ce.getParentIds() + ce.getId() + ",";
                }
            }
        } else if(t instanceof TreeEntity) {
            TreeEntity ce = (TreeEntity)t;
            oldParentIds = ce.getParentIds();
            if(!StringUtil.isBlank(ce.getParentId()) && !"0".equals(ce.getParentId())) {
                ce.setParent(this.get(ce.getParentId()));
            } else {
                try {
                    ce.setParent(ce.getClass().getConstructor(new Class[]{String.class}).newInstance(new Object[]{"0"}));
                } catch (Exception var8) {
//                    Assert.error("no Constructor of class " + ce.getClass().getSimpleName() + " with arguments: String!");
                }
            }

            TreeEntity pe = (TreeEntity)ce.getParent();
            if(pe != null) {
                ce.setParentIds(pe.getParentIds() + pe.getId() + ",");
                if(StringUtil.isNotBlank(oldParentIds) && !oldParentIds.equals(ce.getParentIds())) {
                    newChildParentIds = ce.getParentIds() + ce.getId() + ",";
                }
            }
        }

        if(null != id && !"".equals(id.toString()) && this.isExist(t)) {
            this.update(t);
            if(null != newChildParentIds) {
                Map paraMap = BaseEntity.newParamMap();
                paraMap.put("whereClause", "concat(',',parent_ids,',') like '%," + id + ",%'");
                List<TreeEntity> childList = this.findList(paraMap);
                Iterator var23 = childList.iterator();

                while(var23.hasNext()) {
                    TreeEntity te2 = (TreeEntity)var23.next();
                    te2.setParentIds(newChildParentIds);
                    this.update(te2);
                }
            }
        } else {
            Object i = this.create(t);
            if(t instanceof Map) {
                Map map = (Map)t;
                id = map.get("id");
            } else if(t instanceof BaseEntity) {
                BaseEntity bm = (BaseEntity)t;
                id = bm.getId();
            } else if(i != null) {
                id = i;
            }
        }

        return id;
    }

    public Object create(Object obj) {
        if(obj instanceof BaseEntity) {
            BaseEntity be = (BaseEntity)obj;
            be.preSave();
            if(StringUtil.isBlank(be.getEnable())) {
                be.setEnable("1");
            }

            if(StringUtil.isBlank(be.getDelFlag())) {
                be.setDelFlag("0");
            }
        }

        return this.create("insert", obj);
    }

    public Object create(String sqlId, Object paramObj) {
        if(sqlId.indexOf(".") < 0) {
            sqlId = this.getSqlMapNameSpace() + sqlId;
        }

        return this.baseDao.create(sqlId, paramObj);
    }

    public boolean createBatch(List<?> list) {
        if(list != null && 0 < list.size()) {
            HashMap insertMap = new HashMap();
            List dataList = new ArrayList();

            for(int i = 0; i < list.size(); ++i) {
                dataList.add(list.get(i));
                if(i > 0 && i % 1000 == 0 || i == list.size() - 1) {
                    insertMap.put("list", dataList);
                    this.create("insertBatch", insertMap);
                    dataList = new ArrayList();
                }
            }

            return true;
        } else {
            return false;
        }
    }

    public boolean update(Object obj) {
        if(obj instanceof BaseEntity) {
            ((BaseEntity)obj).preSave();
        }

        return this.update("update", obj);
    }

    public boolean update(String sqlId, Object paramObj) {
        if(sqlId.indexOf(".") < 0) {
            sqlId = this.getSqlMapNameSpace() + sqlId;
        }

        return this.baseDao.update(sqlId, paramObj);
    }

    public int updateBatch(String sqlId, List<?> list) {
        int BATCH_EXE_NUM = 20;
        if(sqlId.indexOf(".") < 0) {
            sqlId = this.getSqlMapNameSpace() + sqlId;
        }

        int i = 0;
        SqlSession sqlSession = this.baseDao.getSqlSession();

        for(int cnt = list.size(); i < cnt; ++i) {
            sqlSession.update(sqlId, list.get(i));
            if((i + 1) % BATCH_EXE_NUM == 0) {
                sqlSession.flushStatements();
            }
        }

        sqlSession.flushStatements();
        sqlSession.close();
        return i;
    }

    public boolean delete(Object obj) {
        return this.delete("delete", obj);
    }

    public boolean deleteByLogic(String id) {
        Map paraMap = new HashMap();
        paraMap.put("id", id);
        paraMap.put("delFlag", "1");
        return this.update("deleteByLogic", paraMap);
    }

    public boolean delete(String sqlId, Object paramObj) {
        if(sqlId.indexOf(".") < 0) {
            sqlId = this.getSqlMapNameSpace() + sqlId;
        }

        return this.baseDao.delete(sqlId, paramObj);
    }

    public D get(String key) {
        return (D) this.get("get", key);
    }

    public Object get(String sqlId, Object paramObj) {
        if(sqlId.indexOf(".") < 0) {
            sqlId = this.getSqlMapNameSpace() + sqlId;
        }

        return this.baseDao.get(sqlId, paramObj);
    }

    public List findList(Object paramObj) {
        return this.findList("findList", paramObj);
    }

    public List findList(String sqlId, Object paramObj) {
        if(sqlId.indexOf(".") < 0) {
            sqlId = this.getSqlMapNameSpace() + sqlId;
        }

        return this.baseDao.findList(sqlId, paramObj);
    }

    public Page findPage(Object paramObj) {
        return this.findPage("findPage", paramObj);
    }

    public Page findPage(String sqlId, Object paramObj) {
        if(sqlId.indexOf(".") < 0) {
            sqlId = this.getSqlMapNameSpace() + sqlId;
        }

        return this.baseDao.findPage(sqlId, paramObj);
    }

    public boolean isExist(Object paramObj) {
        return this.isExist("get", paramObj);
    }

    public boolean isExist(String sqlId, Object paramObj) {
        List dataList = this.findList(sqlId, paramObj);
        return null != dataList && 0 < dataList.size();
    }

    public void execProc(String procId, Object obj) {
        if(procId.indexOf(".") < 0) {
            procId = this.getSqlMapNameSpace() + procId;
        }

        this.baseDao.execProc(procId, obj);
    }

    protected String getSqlMapNameSpace() {
        Class c = this.getClass();
        Type t = c.getGenericSuperclass();
        if(t instanceof ParameterizedType) {
            Type[] p = ((ParameterizedType)t).getActualTypeArguments();
            Class clazz = (Class)p[0];
            return clazz.getName() + ".";
        } else {
//            Assert.error("The type of " + c.getSimpleName() + " parameter T is null!");
            return "";
        }
    }
}
